package com.hui.utils;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.ConvertUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@SuppressWarnings({"rawtypes","unchecked"})
public class MapUtil {
	private static Logger logger=LoggerFactory.getLogger(MapUtil.class);
	/**
	 * 方法描述:实现map转换为实体bean<br/>
	 * 注意:实体类必须要有set方法,否则不能转换
	 * @param map
	 * @param Class.class
	 * @return bean
	 * @Time 2014年8月7日 09:34:51
	 * @author liuwei
	 * */
	public static <T> T getBean(Map<String,Object> param , Class clazz){
		Object value = null;
		Class[] paramTypes = new Class[1];
		Object obj = null;
		try {
			//创建实例
			obj = clazz.newInstance();
			Field[] f = clazz.getDeclaredFields();
			List<Field[]> flist = new ArrayList<Field[]>();
			flist.add(f);
			
			Class superClazz = clazz.getSuperclass();
			while(superClazz != null){
				f = superClazz.getFields();
				flist.add(f);
				superClazz = superClazz.getSuperclass();
			}
			for (Field[] fields : flist) {
				for (Field field : fields) {
					String fieldName = field.getName();
					value = param.get(fieldName);
					if(value == null ) value = param.get(fieldName.toUpperCase());
					if(value == null ) value = param.get(fieldName.toLowerCase());
					if(value != null){
						paramTypes[0] = field.getType();
						Method method = null;
						//调用相应对象的set方法
						StringBuffer methodName = new StringBuffer("set");
						methodName.append(fieldName.substring(0, 1).toUpperCase());
						methodName.append(fieldName.substring(1, fieldName.length()));
						method = clazz.getMethod(methodName.toString(), paramTypes);
						method.invoke(obj, getValue(value.toString(), fieldName, paramTypes[0]));
					}
				}
			}
		} catch (Exception e) {
			logger.debug("",e);
		}
		return (T)obj;
	}
	
	/**
	 * 方法描述:实现bean转换为map集合<br/>
	 * 注意:实体类必须要有set方法,否则不能转换
	 * @param map
	 * @param Object obj
	 * @return Map<String, String>
	 * @Time 2014-08-21 11:35:10
	 * @author liuwei
	 * */
	public static Map<String, Object> getValueMap(Object obj) {  
        Map<String, Object> map = new HashMap<String, Object>();  
        // System.out.println(obj.getClass());  
        // 获取f对象对应类中的所有属性域  
        Field[] fields = obj.getClass().getDeclaredFields();  
        for (int i = 0, len = fields.length; i < len; i++) {  
            String varName = fields[i].getName();  
            try {  
                // 获取原来的访问控制权限  
                boolean accessFlag = fields[i].isAccessible();  
                // 修改访问控制权限  
                fields[i].setAccessible(true);  
                // 获取在对象f中属性fields[i]对应的对象中的变量  
                Object o = fields[i].get(obj);  
                if (o != null)  
                    map.put(varName, o.toString());  
                // 恢复访问控制权限  
                fields[i].setAccessible(accessFlag);  
            } catch (IllegalArgumentException ex) {  
                ex.printStackTrace();  
            } catch (IllegalAccessException ex) {  
                ex.printStackTrace();  
            }  
        }  
        return map;  
  
    }  
	
	
	
	public static<T> T getValue(String value,String fieldName,Class<T> clazz){
		
		if (value == null) { // 如果获取参数值为null,则返回null
			return null;
		} else if (!value.equals("")) { // 如果获取参数值不为"",则通过convertGt方法进行类型转换后返回结果
			return convertGt(value, clazz);
		} else if (clazz.getName().equals(String.class.getName())) { // 如果获取参数值为""
			return convertGt(value, clazz);
		} else {// 如果获取参数值为"",并且clazz不是是String类型,则返回null
			return null;
		}
	}
	
	/**
	 * @param <T>
	 * @param value
	 * @param clazz
	 * @return
	 */
	public static <T> T convertGt(String value, Class<T> clazz) {
		if (value == null) { // 如果值为null,则返回null
			return null;
		} else if (value.equals("")
				&& !clazz.getName().equals(String.class.getName())) { // 如果value值为"",而且要转为的类型不是string类型，那么就统一返回null，也就是空字符串不能转成任何其他类型的实体，只能返回null
			return null;
		} else if (Date.class.getName().equalsIgnoreCase(clazz.getName())) { // 增加对从String类型到Date
			return (T) convertSTD(value);
		}
		return (T) ConvertUtils.convert(value, clazz);
	}

	//日期类型的转换
	private static SimpleDateFormat simpleDateFormate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	
	public static Date convertSTD(String date){
		try {
			return simpleDateFormate.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static String convertDTS(Date date){
		return simpleDateFormate.format(date);
	}
	
	/**
	 * 无用
     * 将一个 Map 对象转化为一个 JavaBean
     * @param type 要转化的类型
     * @param map 包含属性值的 map
     * @return 转化出来的 JavaBean 对象
     * @throws IntrospectionException 如果分析类属性失败
     * @throws IllegalAccessException 如果实例化 JavaBean 失败
     * @throws InstantiationException 如果实例化 JavaBean 失败
     * @throws InvocationTargetException 如果调用属性的 setter 方法失败
     *  
     *
     */
	public static Object convertMap(Class type, Map map)throws Exception{
        BeanInfo beanInfo = Introspector.getBeanInfo(type); // 获取类属性
        Object obj = type.newInstance(); // 创建 JavaBean 对象

        // 给 JavaBean 对象的属性赋值
        PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();
        for (int i = 0; i< propertyDescriptors.length; i++) {
            PropertyDescriptor descriptor = propertyDescriptors[i];
            String propertyName = descriptor.getName();
            if (map.containsKey(propertyName)) {
                // 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
            	Object value = null;
            	try {
            		value = map.get(propertyName);
				} catch (Exception e) {
					logger.debug("",e);
				}
                Object[] args = new Object[1];
                args[0] = value;
                descriptor.getWriteMethod().invoke(obj, args);
            }
        }
        return obj;
    }
	
	
	/**
	 * test
	 * main方法中要想使用log4j必须加载属性配置文件,才可以打印
	 */
	public static void main(String[] args) {
		Map<String,Object>  parame = new HashMap<String,Object>();
		parame.put("u_userid", "001");
		parame.put("u_loginUser", "Kill");
		parame.put("u_password", "izhonghong");
		parame.put("u_createTime","admin0.");
		
		
	}
}
